home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / abuse / src / newlight.c < prev    next >
C/C++ Source or Header  |  1996-04-11  |  21KB  |  889 lines

  1. #include "light.hpp"
  2. #include <stdlib.h>
  3. #include "image.hpp"
  4. #include "macs.hpp"
  5. #include "video.hpp"
  6. #include "palette.hpp"
  7. #include "timing.hpp"
  8. #include "specs.hpp"
  9. #include "dprint.hpp"
  10. #include "filter.hpp"
  11. #include "video.hpp"
  12.  
  13. light_source *first_light_source=NULL;
  14. unsigned char *white_light,*green_light;
  15. unsigned short min_light_level=0;
  16. extern int vmode;
  17.  
  18. int light_detail=MEDIUM_DETAIL;
  19.  
  20. long light_to_number(light_source *l)
  21. {
  22.   
  23.   if (!l) return 0;
  24.   int x=1;
  25.   for (light_source *s=first_light_source;s;s=s->next,x++)
  26.     if (s==l) return x;
  27.   return 0;
  28. }
  29.  
  30.  
  31. light_source *number_to_light(long x)
  32. {
  33.   if (x==0) return NULL;
  34.   x--;
  35.   for (light_source *s=first_light_source;x && s;x--,s=s->next);
  36.   return s;       
  37. }
  38.  
  39. light_source *light_source::copy()
  40. {
  41.   next=new light_source(type,x,y,inner_radius,outer_radius,xshift,yshift,next);
  42.   return next;
  43. }
  44.  
  45. void delete_all_lights()
  46. {
  47.   while (first_light_source)
  48.   {
  49.     light_source *p=first_light_source;
  50.     first_light_source=first_light_source->next;
  51.     delete p;
  52.   }
  53. }
  54.  
  55. void delete_light(light_source *which)
  56. {
  57.   if (which==first_light_source)
  58.   {
  59.     first_light_source=first_light_source->next;
  60.     delete which;
  61.   }
  62.   else
  63.   {
  64.     for (light_source *f=first_light_source;f->next!=which && f;f=f->next);
  65.     if (f)
  66.     {
  67.       f->next=which->next;
  68.       delete which;
  69.     }
  70.   }
  71. }
  72.  
  73. void light_source::calc_range()
  74. {
  75.   switch (type)
  76.   {
  77.     case 0 :
  78.     { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
  79.       x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
  80.     } break;
  81.     case 1 :
  82.     { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
  83.       x2=x+(outer_radius>>xshift); y2=y;
  84.     } break;
  85.     case 2 :
  86.     { x1=x-(outer_radius>>xshift); y1=y;
  87.       x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
  88.     } break;
  89.     case 3 :
  90.     { x1=x; y1=y-(outer_radius>>yshift);
  91.       x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
  92.     } break;
  93.     case 4 :
  94.     { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
  95.       x2=x; y2=y+(outer_radius>>yshift);
  96.     } break;
  97.  
  98.  
  99.     case 5 :
  100.     { x1=x; y1=y-(outer_radius>>yshift);
  101.       x2=x+(outer_radius>>xshift); y2=y;
  102.     } break;
  103.     case 6 :
  104.     { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
  105.       x2=x; y2=y;
  106.     } break;
  107.     case 7 :
  108.     { x1=x-(outer_radius>>xshift); y1=y;
  109.       x2=x; y2=y+(outer_radius>>yshift);
  110.     } break;
  111.     case 8 :
  112.     { x1=x; y1=y;
  113.       x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
  114.     } break;
  115.     case 9 :
  116.     {
  117.       x1=x;
  118.       y1=y;
  119.       x2=x+xshift;
  120.       y2=y+yshift;
  121.     } break;
  122.  
  123.   }
  124.   mul_div=(1<<16)/(outer_radius-inner_radius)*64;
  125. }
  126.  
  127. light_source::light_source(char Type, long X, long Y, long Inner_radius, 
  128.                long Outer_radius, long Xshift,  long Yshift, light_source *Next)
  129.   type=Type; 
  130.   x=X; y=Y; 
  131.   inner_radius=Inner_radius;  
  132.   outer_radius=Outer_radius; 
  133.   next=Next; 
  134.   known=0;
  135.   xshift=Xshift;
  136.   yshift=Yshift;
  137.   calc_range(); 
  138. }
  139.  
  140. light_source *add_light_source(char type, long x, long y, 
  141.                    long inner, long outer, long xshift, long yshift)
  142. {
  143.   first_light_source=new light_source(type,x,y,inner,outer,xshift,yshift,first_light_source);
  144.   return first_light_source;
  145. }
  146.  
  147.  
  148. #define TTINTS 9
  149. uchar *tints[TTINTS];
  150.  
  151. void calc_tint(uchar *tint, int rs, int gs, int bs, int ra, int ga, int ba, palette *pal)
  152. {
  153.   palette npal;
  154.   memset(npal.addr(),0,256);
  155.   for (int i=0;i<256;i++)
  156.   {
  157.     npal.set(i,(int)rs,(int)gs,(int)bs);
  158.     rs+=ra; if (rs>255) rs=255; if (rs<0) rs=0;
  159.     gs+=ga; if (gs>255) gs=255; if (gs<0) gs=0;
  160.     bs+=ba; if (bs>255) bs=255; if (bs<0) bs=0;
  161.   }
  162.   filter f(pal,&npal);
  163.   filter f2(&npal,pal);
  164.  
  165.   for (i=0;i<256;i++,tint++)
  166.     *tint=f2.get_mapping(f.get_mapping(i));
  167. }
  168.  
  169.  
  170. void calc_light_table(palette *pal)
  171. {
  172.   white_light=(unsigned char *)jmalloc(256*64,"light table");
  173.   green_light=(unsigned char *)jmalloc(256*64,"green light");
  174.   for (int i=0;i<TTINTS;i++)
  175.       tints[i]=(uchar *)jmalloc(256,"color tint");
  176.  
  177.   jFILE fp("light.tbl","rb");
  178.   int recalc=0;
  179.   if (fp.open_failure()) recalc=1;
  180.   else
  181.   {
  182.     if (fp.read_short()!=calc_crc((unsigned char *)pal->addr(),768))
  183.       recalc=1;
  184.     else
  185.     {
  186.       fp.read(white_light,256*64);
  187.       fp.read(green_light,256*64);
  188.       for (i=0;i<TTINTS;i++)
  189.         fp.read(tints[i],256);
  190.     }
  191.   }
  192.  
  193.   if (recalc)
  194.   {  
  195.     fprintf(stderr,"Palette has changed, recalculating light table...\n");
  196.     fprintf(stderr,"white : ");
  197.     for (int color=0;color<256;color++)
  198.     {
  199.       unsigned char r,g,b;
  200.       pal->get(color,r,g,b);
  201.       if (color%16==0)
  202.         fprintf(stderr,"%d ",color);
  203.       for (int intensity=63;intensity>=0;intensity--)
  204.       {
  205.     if (r>0 || g>0 || b>0)
  206.           white_light[intensity*256+color]=pal->find_closest(r,g,b);
  207.     else
  208.           white_light[intensity*256+color]=0;
  209.     if (r) r--;  if (g) g--;  if (b) b--;     
  210.       }
  211.     }
  212.  
  213.     fprintf(stderr,"green : ");
  214.     for (color=0;color<256;color++)
  215.     {
  216.       unsigned char r,g,b;
  217.       pal->get(color,r,g,b);
  218.       r=r*3/5; b=b*3/5; g+=7; if (g>255) g=255;
  219.       if (color%16==0)
  220.         fprintf(stderr,"%d ",color);
  221.       for (int intensity=63;intensity>=0;intensity--)
  222.       {
  223.     if (r>0 || g>0 || b>0)
  224.           green_light[intensity*256+color]=pal->find_closest(r,g,b);
  225.     else
  226.           green_light[intensity*256+color]=0;
  227.     if (r) r--;  
  228.     if ((intensity&1)==1)
  229.       if (g) g--;  
  230.     if (b) b--;     
  231.       }
  232.     }
  233.  
  234.     dprintf("\ncalculating tints : \n");
  235.     uchar t[TTINTS*6]={0,0,0,0,0,0, // normal
  236.                    0,0,0,1,0,0,     // red
  237.            0,0,0,1,1,0,     // yellow
  238.            0,0,0,1,0,1,     // purple
  239.            0,0,0,1,1,1,     // gray
  240.            0,0,0,0,1,0,     // green
  241.            0,0,0,0,0,1,     // blue
  242.            0,0,0,0,1,1,     // cyan 
  243.  
  244.  
  245.  
  246.  
  247.  
  248.  
  249.            0,0,0,0,0,0   // reverse green  (night vision effect)
  250.          } ;
  251.     uchar *ti=t+6;
  252.     uchar *c;
  253.     for (i=0,c=tints[0];i<256;i++,c++) *c=i;  // make the normal tint (maps everthing to itself)
  254.     for (i=0,c=tints[TTINTS-1];i<256;i++,c++)  // reverse green
  255.     {
  256.       int r=pal->red(i)/2,g=255-pal->green(i)-30,b=pal->blue(i)*3/5+50;
  257.       if (g<0) g=0;
  258.       if (b>255) b=0;
  259.       *c=pal->find_closest(r,g,b);
  260.     }
  261.  
  262.     // make the colored tints
  263.     for (i=1;i<TTINTS-1;i++)
  264.     {
  265.       calc_tint(tints[i],ti[0],ti[1],ti[2],ti[3],ti[4],ti[5],pal);
  266.       ti+=6;
  267.     }
  268.  
  269.    
  270.  
  271.     jFILE f("light.tbl","wb");
  272.     f.write_short(calc_crc((unsigned char *)pal->addr(),768));
  273.     f.write(white_light,256*64);
  274.     f.write(green_light,256*64);
  275.     for (int i=0;i<TTINTS;i++)
  276.       f.write(tints[i],256);
  277.   }
  278. }
  279.  
  280.  
  281. light_patch *light_patch::copy(light_patch *Next)
  282.   light_patch *p=new light_patch(x1,y1,x2,y2,Next); 
  283.   p->total=total;
  284.   if (total)    
  285.   {
  286.     p->lights=(light_source **)jmalloc(total*sizeof(light_source *),"light patches");
  287.     memcpy(p->lights,lights,total*(sizeof(light_source *)));
  288.   }
  289.   else 
  290.     p->lights=NULL; 
  291.   return p;
  292. }
  293.  
  294. #define MAX_LP 10
  295.  
  296.  
  297. void add_light(light_patch *&first, long x1, long y1, long x2, long y2, 
  298.                 light_source *who)
  299. {  
  300.   light_patch *last=NULL;
  301.   for (light_patch *p=first;p;p=p->next)
  302.   {
  303.     // first see if light patch we are adding is enclosed entirely by another patch
  304.     if (x1>=p->x1 && y1>=p->y1 && x2<=p->x2 && y2<=p->y2)
  305.     {
  306.       if (p->total==MAX_LP) return ;
  307.  
  308.       if (x1>p->x1)
  309.       {
  310.     first=p->copy(first);
  311.     first->x2=x1-1;
  312.       }
  313.       if (x2<p->x2)
  314.       {
  315.     first=p->copy(first);
  316.     first->x1=x2+1;
  317.       }
  318.       if (y1>p->y1)
  319.       {
  320.     first=p->copy(first);
  321.     first->x1=x1;
  322.     first->x2=x2;
  323.     first->y2=y1-1;
  324.       }
  325.       if (y2<p->y2)
  326.       {
  327.     first=p->copy(first);
  328.     first->x1=x1;
  329.     first->x2=x2;
  330.     first->y1=y2+1;
  331.       }
  332.       p->x1=x1; p->y1=y1; p->x2=x2; p->y2=y2;
  333.       p->total++;     
  334.       p->lights=(light_source **)jrealloc(p->lights,sizeof(light_source *)*p->total,"patch_list");
  335.       p->lights[p->total-1]=who;
  336.       return ;
  337.     }
  338.  
  339.     // see if the patch completly covers another patch.
  340.     if (x1<=p->x1 && y1<=p->y1 && x2>=p->x2 && y2>=p->y2)
  341.     {
  342.       if (x1<p->x1)
  343.         add_light(first,x1,y1,p->x1-1,y2,who);
  344.       if (x2>p->x2)
  345.         add_light(first,p->x2+1,y1,x2,y2,who);
  346.       if (y1<p->y1)
  347.         add_light(first,p->x1,y1,p->x2,p->y1-1,who);
  348.       if (y2>p->y2)
  349.         add_light(first,p->x1,p->y2+1,p->x2,y2,who);
  350.       if (p->total==MAX_LP)  return ;
  351.       p->total++;     
  352.       p->lights=(light_source **)jrealloc(p->lights,sizeof(light_source *)*p->total,"patch_list");
  353.       p->lights[p->total-1]=who;
  354.       return ;
  355.     }
  356.  
  357.     // see if we intersect another rect
  358.     if (!(x2<p->x1 || y2<p->y1 || x1>p->x2 || y1>p->y2))  
  359.     {
  360.       int ax1,ay1,ax2,ay2;
  361.       if (x1<p->x1)
  362.       {
  363.         add_light(first,x1,max(y1,p->y1),p->x1-1,min(y2,p->y2),who);
  364.     ax1=p->x1;
  365.       } else
  366.     ax1=x1;
  367.  
  368.       if (x2>p->x2)
  369.       {
  370.         add_light(first,p->x2+1,max(y1,p->y1),x2,min(y2,p->y2),who);
  371.     ax2=p->x2;
  372.       } 
  373.       else
  374.     ax2=x2;
  375.  
  376.       if (y1<p->y1)
  377.       {       
  378.         add_light(first,x1,y1,x2,p->y1-1,who);
  379.     ay1=p->y1;
  380.       } else 
  381.     ay1=y1;
  382.  
  383.       if (y2>p->y2)
  384.       {
  385.         add_light(first,x1,p->y2+1,x2,y2,who);
  386.     ay2=p->y2;
  387.       } else 
  388.     ay2=y2;
  389.  
  390.        
  391.       add_light(first,ax1,ay1,ax2,ay2,who);      
  392.  
  393.       return ;    
  394.     }
  395.   }
  396. }
  397.  
  398. light_patch *find_patch(int screenx, int screeny, light_patch *list)
  399. {
  400.   for (;list;list=list->next)
  401.   {
  402.     if (screenx>=list->x1 && screenx<=list->x2 && screeny>=list->y1 && screeny<=list->y2)
  403.       return list;
  404.   }
  405.   return NULL;
  406. }
  407.  
  408. int calc_light_value(long x, long y, light_patch *which)
  409. {
  410.   int lv=0;
  411.   int t=which->total;
  412.   for (register int i=t-1;i>=0;i--)
  413.   {    
  414.     light_source *fn=which->lights[i];
  415.     if (fn->type==9)
  416.     {
  417.       lv=fn->inner_radius;
  418.       i=0;
  419.     }
  420.     else
  421.     {
  422.       long dx=abs(fn->x-x)<<fn->xshift;
  423.       long dy=abs(fn->y-y)<<fn->yshift;
  424.       long  r2;
  425.       if (dx<dy)
  426.         r2=dx+dy-(dx>>1);
  427.       else r2=dx+dy-(dy>>1);
  428.     
  429.       if (r2>=fn->inner_radius)
  430.       {
  431.     if (r2<fn->outer_radius)
  432.     {
  433.       lv+=((fn->outer_radius-r2)*fn->mul_div)>>16;
  434.     }
  435.       } else lv=63;      
  436.     }
  437.   }
  438.   if (lv>63) return 63; 
  439.   else
  440.     return lv;
  441. }
  442.  
  443.  
  444. void reduce_patches(light_patch *f)   // find constant valued patches
  445. {
  446.   
  447. }
  448.  
  449. light_patch *make_patch_list(int cx1,int cy1,int cx2,int cy2, long screenx, long screeny)
  450. {
  451.   light_patch *first=new light_patch(cx1,cy1,cx2,cy2,NULL);
  452.  
  453.   for (light_source *f=first_light_source;f;f=f->next)   // determine which lights will have effect
  454.   {
  455.     long x1=f->x1-screenx,y1=f->y1-screeny,x2=f->x2-screenx,y2=f->y2-screeny;
  456.     if (x1<cx1) x1=cx1;
  457.     if (y1<cy1) y1=cy1;
  458.     if (x2>cx2) x2=cx2;
  459.     if (y2>cy2) y2=cy2;
  460.  
  461.     if (x1<=x2 && y1<=y2)
  462.       add_light(first,x1,y1,x2,y2,f);
  463.   }
  464.   reduce_patches(first);
  465.  
  466.   return first;
  467. }
  468.  
  469. void delete_patch_list(light_patch *first)
  470. {
  471.   while (first)
  472.   {
  473.     light_patch *p=first;
  474.     first=first->next;
  475.     delete p;
  476.   }
  477. }
  478.  
  479.  
  480. #ifdef __WATCOMC__
  481. extern "C" {
  482. extern long MAP_PUT(long pad, long screen_addr, long remap, long w);
  483. extern long MAP_PUT2(long dest, long screen_addr, long remap, long w);
  484. } ;
  485. #else
  486. inline long MAP_PUT(long pad, long screen_addr, long remap, long w)
  487. { while (w--) 
  488.   { 
  489.     *((uchar *)(screen_addr))=*((uchar *)remap+*((uchar *)screen_addr)); 
  490.     screen_addr++; 
  491.   } 
  492.   return screen_addr;
  493. }
  494.  
  495. inline long MAP_PUT2(long dest_addr, long screen_addr, long remap, long w)
  496. { while (w--) 
  497.   { 
  498.     *((uchar *)(dest_addr))=*((uchar *)remap+*((uchar *)screen_addr)); 
  499.     screen_addr++; 
  500.     dest_addr++;
  501.   } 
  502.   return dest_addr;
  503. }
  504.  
  505. #endif
  506.  
  507.  
  508. inline long calc_lv(light_patch *lp, long sx, long sy)
  509. {
  510.   light_source **lon_p=lp->lights;
  511.   long lv=min_light_level;
  512.   int light_on;
  513.   for (light_on=lp->total-1;light_on>=0;light_on--)
  514.   {
  515.     light_source *fn=*lon_p;
  516.     long *dt=&(*lon_p)->type;
  517.     if (*dt==9)
  518.     {
  519.       lv=fn->inner_radius;
  520.       light_on=0;         
  521.     } else
  522.     {
  523.       dt++;
  524.       int dx=abs(*dt-sx); dt++;
  525.       dx<<=*dt;  dt++;
  526.  
  527.       int dy=abs(*dt-sy); dt++;
  528.       dy<<=*dt;  dt++;
  529.  
  530.       int r2;
  531.       if (dx<dy)
  532.       r2=dx+dy-(dx>>1);
  533.       else r2=dx+dy-(dy>>1);
  534.       
  535.       if (r2<*dt)
  536.       {        
  537.     int v=*dt-r2; dt++;        
  538.     lv+=v*(*dt)>>16;
  539.       }
  540.     }
  541.     lon_p++;
  542.   }
  543.   if (lv>63) return 63;
  544.   else return lv;
  545.  
  546. }
  547.  
  548.  
  549. void light_screen(image *sc, long screenx, long screeny, uchar *light_lookup)
  550. {
  551.   int lx_run,ly_run;
  552.   switch (light_detail) 
  553.   {
  554.     case HIGH_DETAIL : 
  555.     { lx_run=2; ly_run=1; } break;
  556.     case MEDIUM_DETAIL :
  557.     { lx_run=3; ly_run=2; } break;
  558.     case LOW_DETAIL :
  559.     { lx_run=4; ly_run=3; } break;
  560.     case POOR_DETAIL :                   // low detail lighting alread taken care of.
  561.     return ;
  562.   }
  563.  
  564.   short cx1,cy1,cx2,cy2;
  565.   sc->get_clip(cx1,cy1,cx2,cy2);
  566. //  sc->add_dirty(cx1,cy1,cx2,cy2);
  567.   unsigned char *mint=light_lookup+min_light_level*256;
  568.   screenx-=cx1;
  569.   screeny-=cy1;
  570.  
  571.  
  572.   light_patch *first=make_patch_list(cx1,cy1,cx2,cy2,screenx,screeny);
  573.  
  574.  
  575.   int ytry=(1<<ly_run),xtry=(1<<lx_run);
  576.   int calcx_mask=(0xefffffff-(xtry-1));
  577.   int calcy_mask=(0xefffffff-(ytry-1));
  578.   int scr_w=screen->width();
  579.  
  580.   for (light_patch *lp=first;lp;lp=lp->next)
  581.   {
  582.     register int x2=lp->x2;
  583.     if (lp->total==0)  // do dark patches really fast.
  584.     {
  585.       unsigned char *sl=screen->scan_line(lp->y1)+lp->x1,*dest;
  586. #ifdef __WATCOMC__
  587.       if (get_vmode()==19) dest=(uchar *)0xa0000+lp->y1*320+lp->x1;
  588.       else dest=sl;
  589. #else
  590.       dest=sl;
  591. #endif
  592.       
  593.       int y2=lp->y2;
  594.       for (int y=lp->y1;y<=y2;y++,sl+=scr_w,dest+=scr_w)
  595.       {
  596.     int w=lp->x2-lp->x1+1;
  597.         MAP_PUT2((long)dest,(long)sl,(long)mint,w);
  598.       }
  599.     }
  600.     else
  601.     {
  602.       int todoy;
  603.       int y2=lp->y2;
  604.  
  605.       int xmask=(xtry-1);
  606.       int ymask=(ytry-1);
  607.  
  608.       uchar *yaddr=screen->scan_line(lp->y1)+lp->x1,*dyaddr;
  609. #ifdef __WATCOMC__
  610.       if (get_vmode()==19) dyaddr=((uchar *)0xa0000)+lp->y1*320+lp->x1;
  611.       else dyaddr=yaddr;
  612. #else
  613.       dyaddr=yaddr;
  614. #endif
  615.  
  616.       for (int y=lp->y1;y<=y2;)
  617.       {
  618.     long sy=(screeny+y);
  619.     if (y+ytry>lp->y2)        // see how many y lines to do for this block
  620.       todoy=lp->y2-y+1;
  621.     else todoy=ytry;
  622.     int maxy=ytry-(sy&ymask);
  623.     if (todoy>maxy)
  624.       todoy=maxy;
  625.     
  626.     uchar *xaddr=yaddr,*dxaddr=dyaddr;
  627.     for (register int x=lp->x1;x<=x2;)
  628.     {
  629.       long lv=min_light_level;
  630.       unsigned char *ct;
  631.       light_source *f;
  632.       int todox;
  633.       if (x+xtry>lp->x2)
  634.         todox=lp->x2-x+1;
  635.       else todox=xtry;
  636.       int sx=(screenx+x);
  637.       int max=xtry-(sx&xmask);
  638.       if (todox>max)
  639.         todox=max;
  640.  
  641.  
  642.       ct=light_lookup+calc_lv(lp,sx,sy)*256;
  643.       switch (todox)
  644.       {
  645.         case 8 :
  646.         {
  647.           x+=8;
  648.           switch (todoy)
  649.           {
  650.         case 4 :
  651.         {
  652.           uchar *addr=xaddr,*daddr=dxaddr;
  653.           dxaddr=(uchar *)MAP_PUT2((long)daddr,(long)addr,(long)ct,8); 
  654.           xaddr+=8;
  655.  
  656.           addr+=scr_w; daddr+=scr_w;
  657.           MAP_PUT2((long)daddr,(long)addr,(long)ct,8);   addr+=scr_w; daddr+=scr_w;
  658.           MAP_PUT2((long)daddr,(long)addr,(long)ct,8);   addr+=scr_w; daddr+=scr_w;
  659.           MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
  660.         } break;
  661.         case 3 :
  662.         {
  663.           uchar *addr=xaddr,*daddr=dxaddr;
  664.           dxaddr=(uchar *)MAP_PUT2((long)daddr,(long)addr,(long)ct,8); 
  665.           xaddr+=8;
  666.  
  667.           addr+=scr_w; daddr+=scr_w;
  668.           MAP_PUT2((long)daddr,(long)addr,(long)ct,8);   addr+=scr_w; daddr+=scr_w;
  669.           MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
  670.  
  671.  
  672.         } break;         
  673.         case 2 :
  674.         {
  675.           uchar *addr=xaddr,*daddr=dxaddr;
  676.           dxaddr=(uchar *)MAP_PUT2((long)daddr,(long)addr,(long)ct,8); 
  677.           xaddr+=8;
  678.  
  679.           addr+=scr_w; daddr+=scr_w;
  680.           MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
  681.  
  682.         } break;
  683.         case 1 : 
  684.         { dxaddr=(uchar *)MAP_PUT((long)dxaddr,(long)xaddr,(long)ct,8); 
  685.           xaddr+=8;           
  686.         } break;
  687.           }
  688.         } break;
  689. /*        case 4 :
  690.         {
  691.           x+=4;
  692.           switch (todoy)
  693.           {
  694.         case 4 :
  695.         {
  696.           uchar *addr=xaddr;
  697.           xaddr=(uchar *)MAP_PUT(0,(long)addr,(long)ct,4); addr+=scr_w; daddr+=scr_w;
  698.           MAP_PUT(0,(long)addr,(long)ct,4);                addr+=scr_w; daddr+=scr_w;
  699.           MAP_PUT(0,(long)addr,(long)ct,4);                addr+=scr_w; daddr+=scr_w;
  700.           MAP_PUT(0,(long)addr,(long)ct,4);
  701.         } break;
  702.         case 3 :
  703.         {
  704.           uchar *addr=xaddr;
  705.           xaddr=(uchar *)MAP_PUT(0,(long)addr,(long)ct,4); addr+=scr_w;  daddr+=scr_w;
  706.           MAP_PUT(0,(long)addr,(long)ct,4);                addr+=scr_w;  daddr+=scr_w;
  707.           MAP_PUT(0,(long)addr,(long)ct,4);
  708.         } break;         
  709.         case 2 :
  710.         {
  711.           uchar *addr=xaddr;
  712.           xaddr=(uchar *)MAP_PUT(0,(long)addr,(long)ct,4); addr+=scr_w; daddr+=scr_w;
  713.           MAP_PUT(0,(long)addr,(long)ct,4);
  714.         } break;
  715.         case 1 : xaddr=(uchar *)MAP_PUT(0,(long)xaddr,(long)ct,4); break;
  716.           }
  717.         } break; */
  718.         default :
  719.         {
  720.           x+=todox;
  721.           if (todoy==1)
  722.           {
  723.             dxaddr=(uchar *)MAP_PUT2((long)dxaddr,(long)xaddr,(long)ct,todox);
  724.         xaddr+=todox;
  725.           }
  726.           else
  727.           {
  728.         uchar *addr=xaddr,*daddr=dxaddr;
  729.         dxaddr=(uchar *)MAP_PUT2((long)dxaddr,(long)xaddr,(long)ct,todox); 
  730.         xaddr+=todox;
  731.  
  732.         addr+=scr_w;
  733.         daddr+=scr_w;
  734.  
  735.         int cc=todoy-1;
  736.         while (cc--)
  737.         {
  738.           MAP_PUT2((long)daddr,(long)addr,(long)ct,todox); 
  739.           addr+=scr_w;
  740.           daddr+=scr_w;
  741.         }                  
  742.           }
  743.         }
  744.       }
  745.     }
  746.              
  747.     int yadd=scr_w*todoy;
  748.     yaddr+=yadd;
  749.     dyaddr+=yadd;
  750.  
  751.     y+=todoy;
  752.       }
  753.     }
  754.   }
  755.   while (first)
  756.   {
  757.     light_patch *p=first;
  758.     first=first->next;
  759.     delete p;
  760.   }
  761. }
  762.  
  763.  
  764.  
  765.  
  766. void add_light_spec(spec_directory *sd, char *level_name)
  767. {
  768.   long size=4+4;  // number of lights and minimum light levels
  769.   for (light_source *f=first_light_source;f;f=f->next)
  770.     size+=6*4+1;
  771.   sd->add(new spec_entry(SPEC_LIGHT_LIST,"lights",NULL,size,0));  
  772. }
  773.  
  774. void write_lights(jFILE *fp)
  775. {
  776.   int t=0;
  777.   for (light_source *f=first_light_source;f;f=f->next) t++;
  778.   fp->write_long(t);
  779.   fp->write_long(min_light_level);
  780.   for (f=first_light_source;f;f=f->next)
  781.   {
  782.     fp->write_long(f->x);
  783.     fp->write_long(f->y);
  784.     fp->write_long(f->xshift);
  785.     fp->write_long(f->yshift);
  786.     fp->write_long(f->inner_radius);
  787.     fp->write_long(f->outer_radius);
  788.     fp->write_byte(f->type);
  789.   }
  790. }
  791.  
  792.  
  793. int send_lights(net_descriptor *os)
  794. {
  795.   packet pk;
  796.   int t=0;
  797.   for (light_source *f=first_light_source;f;f=f->next) t++;
  798.   pk.write_long(t);
  799.   pk.write_short(min_light_level);
  800.   if (!os->send(pk)) return 0;
  801.   for (f=first_light_source;f;f=f->next)
  802.   {
  803.     pk.reset();
  804.     pk.write_long(f->x);
  805.     pk.write_long(f->y);
  806.     pk.write_long(f->xshift);
  807.     pk.write_long(f->yshift);
  808.     pk.write_long(f->inner_radius);
  809.     pk.write_long(f->outer_radius);
  810.     pk.write_long(f->type);
  811.     if (!os->send(pk)) return 0;   
  812.   }
  813.   return 1;
  814. }
  815.  
  816.  
  817. void read_lights(spec_directory *sd, jFILE *fp, char *level_name)
  818. {
  819.   delete_all_lights();
  820.   spec_entry *se=sd->find("lights");
  821.   if (se)
  822.   {
  823.     fp->seek(se->offset,SEEK_SET);
  824.     long t=fp->read_long();
  825.     min_light_level=fp->read_long();
  826.     light_source *last;
  827.     while (t)
  828.     {
  829.       t--;
  830.       long x=fp->read_long();
  831.       long y=fp->read_long();
  832.       long xshift=fp->read_long();
  833.       long yshift=fp->read_long();
  834.       long ir=fp->read_long();
  835.       long ora=fp->read_long();
  836.       long ty=fp->read_byte();
  837.  
  838.       light_source *p=new light_source(ty,x,y,ir,ora,xshift,yshift,NULL);
  839.       
  840.       if (first_light_source)
  841.         last->next=p;
  842.       else first_light_source=p;
  843.       last=p;
  844.     }
  845.   }
  846. }
  847.  
  848.  
  849. int receive_lights(net_descriptor *os)
  850. {
  851.   packet pk;
  852.   if (!os->get(pk)) { printf("net error : light total\n"); return 0; }
  853.   long t; 
  854.   if (pk.read((uchar *)&t,4)!=4)
  855.   { printf("net error : (t) packet incomplete\n"); return 0; }
  856.   t=lltl(t);
  857.  
  858.   if (pk.read((uchar *)&min_light_level,2)!=2)
  859.   { printf("net error : (minl) packet incomplete\n"); return 0; }
  860.   min_light_level=lstl(min_light_level);
  861.  
  862.   light_source *last;
  863.   printf("Reading %d lights\n",t); 
  864.   while (t)
  865.   {
  866.     if (!os->get(pk)) {printf("net error : read light\n"); return 0; }
  867.     t--;
  868.     long dt[7];
  869.     if (pk.read((uchar *)dt,7*4)!=7*4) return 0;
  870.  
  871.  
  872.     light_source *p=new light_source(lltl(dt[6]),
  873.                        lltl(dt[0]),lltl(dt[1]),
  874.                        lltl(dt[4]),lltl(dt[5]),
  875.                        lltl(dt[2]),lltl(dt[3]),NULL);
  876.       
  877.     if (first_light_source)
  878.       last->next=p;
  879.     else first_light_source=p;
  880.       last=p;
  881.   }
  882.   return 1;
  883. }
  884.  
  885.  
  886.  
  887.